﻿using System;
using System.Text;
using GeoAPI.Geometries;
using NetTopologySuite.Utilities;

namespace NetTopologySuite.Algorithm
{
	public abstract class LineIntersector
	{
		public static double ComputeEdgeDistance(Coordinate p, Coordinate p0, Coordinate p1)
		{
			double num = System.Math.Abs(p1.X - p0.X);
			double num2 = System.Math.Abs(p1.Y - p0.Y);
			double num3;
			if (p.Equals(p0))
			{
				num3 = 0.0;
			}
			else if (p.Equals(p1))
			{
				num3 = ((num > num2) ? num : num2);
			}
			else
			{
				double num4 = System.Math.Abs(p.X - p0.X);
				double num5 = System.Math.Abs(p.Y - p0.Y);
				num3 = ((num > num2) ? num4 : num5);
				if (num3 == 0.0 && !p.Equals2D(p0))
				{
					num3 = System.Math.Max(num4, num5);
				}
			}
			Assert.IsTrue(num3 != 0.0 || p.Equals(p0), "Bad distance calculation");
			return num3;
		}

		public static double NonRobustComputeEdgeDistance(Coordinate p, Coordinate p1, Coordinate p2)
		{
			double num = p.X - p1.X;
			double num2 = p.Y - p1.Y;
			double num3 = System.Math.Sqrt(num * num + num2 * num2);
			Assert.IsTrue(num3 != 0.0 || p.Equals(p1), "Invalid distance calculation");
			return num3;
		}

		protected Coordinate Pa
		{
			get
			{
				return this.IntersectionPoint[0];
			}
		}

		protected Coordinate Pb
		{
			get
			{
				return this.IntersectionPoint[1];
			}
		}

		protected LineIntersector()
		{
			this.InputLines = new Coordinate[2][];
			this.InputLines[0] = new Coordinate[2];
			this.InputLines[1] = new Coordinate[2];
			this.IntersectionPoint[0] = new Coordinate();
			this.IntersectionPoint[1] = new Coordinate();
			this.Result = 0;
		}

		[Obsolete("Use PrecisionModel instead")]
		public IPrecisionModel MakePrecise
		{
			set
			{
				this._precisionModel = value;
			}
		}

		public IPrecisionModel PrecisionModel
		{
			get
			{
				return this._precisionModel;
			}
			set
			{
				this._precisionModel = value;
			}
		}

		public Coordinate GetEndpoint(int segmentIndex, int ptIndex)
		{
			return this.InputLines[segmentIndex][ptIndex];
		}

		public abstract void ComputeIntersection(Coordinate p, Coordinate p1, Coordinate p2);

		protected bool IsCollinear
		{
			get
			{
				return this.Result == LineIntersector.CollinearIntersection;
			}
		}

		public void ComputeIntersection(Coordinate p1, Coordinate p2, Coordinate p3, Coordinate p4)
		{
			this.InputLines[0][0] = p1;
			this.InputLines[0][1] = p2;
			this.InputLines[1][0] = p3;
			this.InputLines[1][1] = p4;
			this.Result = this.ComputeIntersect(p1, p2, p3, p4);
		}

		public abstract int ComputeIntersect(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2);

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(this.InputLines[0]).Append("-");
			stringBuilder.Append(this.InputLines[1]).Append(" ");
			stringBuilder.Append(this.InputLines[2]).Append("-");
			stringBuilder.Append(this.InputLines[3]).Append(" : ");
			if (this.IsEndPoint)
			{
				stringBuilder.Append(" endpoint");
			}
			if (this._isProper)
			{
				stringBuilder.Append(" proper");
			}
			if (this.IsCollinear)
			{
				stringBuilder.Append(" collinear");
			}
			return stringBuilder.ToString();
		}

		protected bool IsEndPoint
		{
			get
			{
				return this.HasIntersection && !this._isProper;
			}
		}

		public bool HasIntersection
		{
			get
			{
				return this.Result != LineIntersector.NoIntersection;
			}
		}

		public int IntersectionNum
		{
			get
			{
				return this.Result;
			}
		}

		public Coordinate GetIntersection(int intIndex)
		{
			return this.IntersectionPoint[intIndex];
		}

		protected void ComputeIntLineIndex()
		{
			if (this.IntersectionLineIndex != null)
			{
				return;
			}
			this.IntersectionLineIndex = new int[4];
			this.ComputeIntLineIndex(0);
			this.ComputeIntLineIndex(1);
		}

		public bool IsIntersection(Coordinate pt)
		{
			for (int i = 0; i < this.Result; i++)
			{
				if (this.IntersectionPoint[i].Equals2D(pt))
				{
					return true;
				}
			}
			return false;
		}

		public bool IsInteriorIntersection()
		{
			return this.IsInteriorIntersection(0) || this.IsInteriorIntersection(1);
		}

		public bool IsInteriorIntersection(int inputLineIndex)
		{
			for (int i = 0; i < this.Result; i++)
			{
				if (!this.IntersectionPoint[i].Equals2D(this.InputLines[inputLineIndex][0]) && !this.IntersectionPoint[i].Equals2D(this.InputLines[inputLineIndex][1]))
				{
					return true;
				}
			}
			return false;
		}

		public bool IsProper
		{
			get
			{
				return this.HasIntersection && this._isProper;
			}
			protected set
			{
				this._isProper = value;
			}
		}

		public Coordinate GetIntersectionAlongSegment(int segmentIndex, int intIndex)
		{
			this.ComputeIntLineIndex();
			int num = (segmentIndex == 0) ? 0 : 2;
			return this.IntersectionPoint[this.IntersectionLineIndex[num + intIndex]];
		}

		public int GetIndexAlongSegment(int segmentIndex, int intIndex)
		{
			this.ComputeIntLineIndex();
			int num = (segmentIndex == 0) ? 0 : 2;
			return this.IntersectionLineIndex[num + intIndex];
		}

		protected void ComputeIntLineIndex(int segmentIndex)
		{
			double edgeDistance = this.GetEdgeDistance(segmentIndex, 0);
			double edgeDistance2 = this.GetEdgeDistance(segmentIndex, 1);
			if (edgeDistance > edgeDistance2)
			{
				int num = (segmentIndex == 0) ? 0 : 2;
				this.IntersectionLineIndex[num] = 0;
				this.IntersectionLineIndex[num + 1] = 1;
				return;
			}
			int num2 = (segmentIndex == 0) ? 0 : 2;
			this.IntersectionLineIndex[num2] = 1;
			this.IntersectionLineIndex[num2 + 1] = 0;
		}

		public double GetEdgeDistance(int segmentIndex, int intIndex)
		{
			return LineIntersector.ComputeEdgeDistance(this.IntersectionPoint[intIndex], this.InputLines[segmentIndex][0], this.InputLines[segmentIndex][1]);
		}

		[Obsolete("Ambiguous naming, use NoIntersection")]
		public const int DontIntersect = 0;

		[Obsolete("Ambiguous naming, use PointIntersection")]
		public const int DoIntersect = 1;

		[Obsolete("Ambiguous naming, use CollinearIntersection")]
		public const int Collinear = 2;

		public static readonly int NoIntersection = 0;

		public static readonly int PointIntersection = 1;

		public static readonly int CollinearIntersection = 2;

		protected int Result;

		protected Coordinate[][] InputLines;

		protected Coordinate[] IntersectionPoint = new Coordinate[2];

		protected int[] IntersectionLineIndex;

		private bool _isProper;

		private IPrecisionModel _precisionModel;
	}
}
